<template>
  <transition name="custom-dialog-fade">
    <div v-if="visible" class="custom-dialog-overlay" @click.self="handleOverlayClick">
      <div ref="dialogRef" class="custom-dialog" :style="dialogStyle" :class="$attrs.class">
        <div class="custom-dialog-header" @mousedown="startDrag">
          <span class="custom-dialog-title">{{ title }}</span>
          <button class="custom-dialog-close" @click="close">
            <el-icon><Close /></el-icon>
          </button>
        </div>
        <div class="custom-dialog-body">
          <slot></slot>
        </div>
        <div v-if="$slots.footer" class="custom-dialog-footer">
          <slot name="footer"></slot>
        </div>
        <div class="custom-dialog-resizer" @mousedown.stop="startResize"></div>
      </div>
    </div>
  </transition>
</template>

<script setup lang="ts">
import { ref, computed, watch } from 'vue'
import { Close } from '@element-plus/icons-vue'

interface Props {
  modelValue: boolean
  title: string
  width?: string
  height?: string
  top?: string
  closeOnClickModal?: boolean
}

const props = withDefaults(defineProps<Props>(), {
  width: '50%',
  height: 'auto',
  top: '15vh',
  closeOnClickModal: true
})

const emit = defineEmits(['update:modelValue'])

const visible = computed({
  get: () => props.modelValue,
  set: (value) => emit('update:modelValue', value)
})

const dialogRef = ref<HTMLElement | null>(null)
const position = ref({ x: 0, y: 0 })
const size = ref({ width: 0, height: 0 })
const isPositionInitialized = ref(false)
const isDragging = ref(false)
const isResizing = ref(false)

const dialogStyle = computed(() => {
  const style: Record<string, string> = {}
  if (size.value.width) {
    style.width = `${size.value.width}px`
  } else {
    style.width = props.width
  }
  if (size.value.height) {
    style.height = `${size.value.height}px`
  } else {
    style.height = props.height
  }

  if (!isPositionInitialized.value) {
    style.top = props.top
    style.left = '50%'
    style.transform = 'translateX(-50%)'
  } else {
    style.top = `${position.value.y}px`
    style.left = `${position.value.x}px`
    style.transform = 'none'
    style.marginTop = '0'
  }
  return style
})

const close = () => {
  visible.value = false
}

const handleOverlayClick = () => {
  if (props.closeOnClickModal) {
    close()
  }
}

// Draggable functionality
const dragStartX = ref(0)
const dragStartY = ref(0)
const initialDialogPosition = { x: 0, y: 0 }

const startDrag = (event: MouseEvent) => {
  if (!dialogRef.value) return
  if ((event.target as HTMLElement).closest('button, input, select, textarea')) {
    return;
  }
  isDragging.value = true
  event.preventDefault();

  dragStartX.value = event.clientX
  dragStartY.value = event.clientY

  const rect = dialogRef.value.getBoundingClientRect()
  initialDialogPosition.x = rect.left
  initialDialogPosition.y = rect.top

  if (!isPositionInitialized.value) {
    isPositionInitialized.value = true
    position.value = { x: rect.left, y: rect.top }
  }

  document.addEventListener('mousemove', onDrag)
  document.addEventListener('mouseup', stopDrag)
}

const onDrag = (event: MouseEvent) => {
  if (!isDragging.value) return
  const deltaX = event.clientX - dragStartX.value
  const deltaY = event.clientY - dragStartY.value

  position.value = {
    x: initialDialogPosition.x + deltaX,
    y: initialDialogPosition.y + deltaY,
  }
}

const stopDrag = () => {
  isDragging.value = false
  document.removeEventListener('mousemove', onDrag)
  document.removeEventListener('mouseup', stopDrag)
}

// Resizable functionality
const resizeStartX = ref(0)
const resizeStartY = ref(0)
const initialDialogSize = { width: 0, height: 0 }

const startResize = (event: MouseEvent) => {
  if (!dialogRef.value) return
  isResizing.value = true
  event.preventDefault()

  resizeStartX.value = event.clientX
  resizeStartY.value = event.clientY

  const rect = dialogRef.value.getBoundingClientRect()
  initialDialogSize.width = rect.width
  initialDialogSize.height = rect.height

  if (!size.value.width) {
    size.value = { width: rect.width, height: rect.height }
  }

  document.addEventListener('mousemove', onResize)
  document.addEventListener('mouseup', stopResize)
}

const onResize = (event: MouseEvent) => {
  if (!isResizing.value) return
  const deltaX = event.clientX - resizeStartX.value
  const deltaY = event.clientY - resizeStartY.value

  size.value = {
    width: initialDialogSize.width + deltaX,
    height: initialDialogSize.height + deltaY,
  }
}

const stopResize = () => {
  isResizing.value = false
  document.removeEventListener('mousemove', onResize)
  document.removeEventListener('mouseup', stopResize)
}

watch(visible, (newVal) => {
  if (newVal) {
    // Reset size when dialog opens to use prop values
    size.value = { width: 0, height: 0 };
  } else {
    isPositionInitialized.value = false;
  }
});
</script>

<style scoped>
.custom-dialog-fade-enter-active,
.custom-dialog-fade-leave-active {
  transition: opacity 0.3s ease;
}

.custom-dialog-fade-enter-from,
.custom-dialog-fade-leave-to {
  opacity: 0;
}

.custom-dialog-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.7);
  z-index: 2000;
}

.custom-dialog {
  background-color: #1a1a1a;
  color: #f0f0f0;
  border: 1px solid #333;
  border-radius: 8px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.7);
  display: flex;
  flex-direction: column;
  position: absolute;
  min-width: 300px; /* Minimum size */
  min-height: 200px;
}

.custom-dialog-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 24px;
  border-bottom: 1px solid #333;
  cursor: move;
  background-color: #222;
  border-top-left-radius: 8px;
  border-top-right-radius: 8px;
}

.custom-dialog-title {
  font-size: 18px;
  font-weight: 600;
  color: #ffffff;
}

.custom-dialog-close {
  background: transparent;
  border: none;
  cursor: pointer;
  font-size: 16px;
  color: #888;
}

.custom-dialog-close:hover {
  color: #fff;
}

.custom-dialog-body {
  padding: 24px;
  flex-grow: 1;
  overflow-y: auto;
}

.custom-dialog-footer {
  padding: 16px 24px;
  border-top: 1px solid #333;
  text-align: right;
  background-color: #222;
  border-bottom-left-radius: 8px;
  border-bottom-right-radius: 8px;
}

.custom-dialog-resizer {
  position: absolute;
  bottom: 0;
  right: 0;
  width: 12px;
  height: 12px;
  cursor: se-resize;
  background: transparent;
}
</style>